package com;

import com.google.common.base.CharMatcher;
import com.google.common.base.Splitter;

import java.util.List;
import java.util.Objects;

import static com.google.common.base.Preconditions.checkArgument;

/**
 * @author 张述江
 * @date 2023-08-28
 */
public class Property {
    private static final Splitter NAME_VALUE_SPLITTER = Splitter.on('=').limit(2);
    private static final CharMatcher PRINTABLE_ASCII = CharMatcher.inRange((char) 0x21, (char) 0x7E); // spaces are not allowed

    private final String name;
    private final String value;

    public Property(String property) {
        List<String> nameValue = NAME_VALUE_SPLITTER.splitToList(property);
        checkArgument(nameValue.size() == 2, "Invalid property: %s", property);
        name = nameValue.get(0);
        value = nameValue.get(1);

        verifyProperty(name, value);

        System.out.printf("create property from property string (%s)\n", property);
    }

    private static void verifyProperty(String name, String value) {
        checkArgument(!name.isEmpty(), "Session property name is empty");
        checkArgument(name.indexOf('=') < 0, "Session property name must not contain '=': %s", name);
        checkArgument(PRINTABLE_ASCII.matchesAllOf(name), "Session property name contains spaces or is not US_ASCII: %s", name);
        checkArgument(PRINTABLE_ASCII.matchesAllOf(value), "Session property value contains spaces or is not US_ASCII: %s", value);
    }

    public String getName() {
        return name;
    }

    public String getValue() {
        return value;
    }

    @Override
    public String toString() {
        return name + '=' + value;
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, value);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null || getClass() != obj.getClass()) {
            return false;
        }
        Property other = (Property) obj;
        return Objects.equals(this.name, other.name) &&
                Objects.equals(this.value, other.value);
    }
}
